home *** CD-ROM | disk | FTP | other *** search
/ CD Ware Multimedia 1994 November / Cd Ware (Nro. 2) - Epimundo.iso / DOS / PG / CHART.ZIP / CMAIN.86 < prev    next >
Encoding:
Text File  |  1993-11-01  |  36.3 KB  |  1,402 lines

  1. ;Chart V1.23 Copyright 1992-1993 Andrew Sprott
  2.  
  3. ;The source files:
  4.  
  5. ;    CMAIN.86
  6. ;    CFLOW1.86
  7. ;    CFLOW2.86
  8. ;    CSUB1.86
  9. ;    CSUB2.86
  10. ;    CSUB3.86
  11. ;    CSYS.86
  12. ;    CWORK.86
  13.  
  14. ;should be accompanied with the file CHART.PJT, which is a PcWord version 1
  15. ;project file and contains the tabs and hypertext data for each source file.
  16. ;Make sure all of the files are in the same directory and PCWORD.EXE or
  17. ;HYPEREAD.COM is within the scope of the DOS PATH and enter:
  18.  
  19. ;    PCWORD CHART.PJT
  20.  
  21. ;or load CHART.PJT from within PcWord.
  22.  
  23. ;or enter
  24.  
  25. ;    HYPEREAD CHART.PJT
  26.  
  27. ;To assemble CHART, you requires A86.COM version 3.21 or higher.
  28. ;Make sure the source files (*.86) and the file CHART. are in the same
  29. ;directory. Then assemble with the line
  30.  
  31. ;A86 +E <CHART. &
  32.  
  33. ;You may have noticed that the source file CPRINT.86 isn't included in the list
  34. ;above. This is because the printing function is incomplete as I gave up on it.
  35. ;The rest of the program works ok though.
  36.  
  37.         ;equates
  38.  
  39.         pull equ pop
  40.         pullf equ popf
  41.         o equ offset
  42.  
  43.         ;equates
  44.  
  45. ;Each box has a record and a descripter string. The record is defined as below.
  46. ;The colour scheme for box record elements is GREEN
  47.  
  48.         previous equ 0    ;box lead from
  49.         yes equ 2    ;yes route or single route
  50.         no equ 4    ;no route
  51.         child equ 6    ;child flowchart, 0 if none
  52.         parent equ 8    ;parent box
  53.         descripter_length equ 10    ;size of descripter string
  54.         descripter equ 12    ;descripter 20 bit address
  55.         box_temp equ 16    ;temporary store (used by renumber and
  56.             ;printing routines)
  57.         box_record equ 18    ;size of box record
  58.  
  59. ;Other box references are light GREEN
  60.  
  61.         first_box equ 6    ;first box number
  62.         box_top equ 16383-first_box    ;highest box allowed
  63.  
  64.         option_count equ 22    ;total number of options available
  65.         menu_options equ 6    ;menu option count
  66.  
  67. ;All box stack references are RED
  68.  
  69.         top_stack equ 0fffch    ;offset to top of subchart stack
  70.         bottom_stack equ 0f000h    ;allow 4096 for box stack
  71.  
  72.         novid equ 7    ;normal video attribute
  73.         revid equ 070h    ;reverse video attribute
  74.  
  75.         crtc_cstart equ 0ah    ;cursor start address register
  76.         crtc_cend equ 0bh    ;cursor end address register
  77.  
  78.         crtc_clochigh equ 0eh    ;cursor location msw
  79.         crtc_cloclow equ 0fh    ;cursor location lsw
  80.  
  81.         code segment
  82.  
  83.         call head    ;initialise program
  84. main:
  85.         call body    ;goto main loop
  86.         call tail    ;check if flowchart needs saving
  87.         jc main    ;go back to main menu if escape pressed
  88.  
  89.         ;exit
  90.  
  91. exit:
  92.         call restore_cursor    ;restore cursor type
  93.         mov ax,04c00h    ;load function parameters
  94.         int 021h    ;exit
  95.  
  96.         ;set up stack
  97.  
  98. c1:
  99.         pull bp    ;load return address
  100.         mov ax,w[2]    ;load ram top segment
  101.         sub ax,01000h    ;subtract a segment from it
  102.         cli    ;disable interrupts
  103.         mov sp,-2    ;store stack pointer
  104.         mov ss,ax    ;store stack segment
  105.         sti    ;enable interrupts
  106.  
  107.         ;calculate ram top
  108.  
  109.         sub ax,0100h    ;leave 4k for stack
  110.         mov w stack_segment,ax    ;store it as top of subchart stack
  111.         sub ax,0100h    ;allow 4k for box stack
  112.         xor si,si    ;convert stack pointer to address
  113.         call ptr_addr
  114.         mov w ram_top,ax    ;save it
  115.         mov w ram_top+2,dx
  116.  
  117.         ;initialise chart flags
  118.  
  119.         mov ax,si    ;load zero
  120.         mov b chart_flag,al    ;start at beggining of editing loop
  121.         mov b search_string,al    ;clear search string buffer
  122.         mov w next_box,ax    ;indicate no chart loaded
  123.         mov w current_box,ax
  124.  
  125.         ;calculate address of start of box records
  126.  
  127.         mov ax,cs    ;load code segment
  128.         xor dx,dx    ;extend accumulator
  129.         shl ax,1    ;convert segment to address
  130.         rcl dx,1
  131.         shl ax,1
  132.         rcl dx,1
  133.         shl ax,1
  134.         rcl dx,1
  135.         shl ax,1
  136.         rcl dx,1
  137.         add ax,o start_of_chart    ;add program size
  138.         adc dx,0
  139.         mov w chart,ax    ;store address to start of box data
  140.         mov w chart+2,dx
  141.         mov w start_free_memory,ax    ;store address to box descripter store
  142.         mov w start_free_memory+2,dx
  143.  
  144.         ;set screen mode as 80 column text mode
  145.  
  146.         call init_screen    ;initialise screen
  147.         mov w exit_cursor_type,cx    ;save type of cursor
  148.         push bp    ;save return address
  149.         xor dx,dx    ;load zero
  150.         mov di,o filename    ;load offset to filename buffer
  151.         xchg dx,w[di]    ;is a flowchart filename supplied?
  152.         or dx,dx
  153.         je ret    ;exit if not
  154.  
  155.         ;copy filename to flowchart
  156.  
  157.         mov si,dx    ;copy offset to start of filename
  158.         mov es,ax,cs    ;copy segment to buffer
  159. a1:
  160.         lodsb    ;load character from filename
  161.         stosb    ;write to filename buffer
  162.         or al,al    ;end of filename?
  163.         jne a1    ;copy next character if not
  164.         call load_chart_dx    ;load alternative chart if yes
  165.         ret    ;exit to body if not
  166.  
  167.         ;initialise program
  168.  
  169. head:
  170.         xor ax,ax    ;load zero
  171.         mov b middle_5,al    ;indicate not in shell
  172.         mov w filename,ax    ;indicate no filename supplied
  173.         dec ax
  174.         mov b new_chart,al
  175.         mov b direct_video,al    ;indicate writing direct to video
  176.  
  177.         ;copy crtc address for current display mode
  178.  
  179.         inc ax    ;load zero
  180.         mov ds,ax    ;copy segment to bios workspace
  181.         mov ax,w[0463h]    ;copy crtc address to whatever is active
  182.         mov ds,dx,cs    ;restore segment register
  183.         mov w crtc_address,ax
  184.  
  185.         ;set defaults
  186.  
  187.         xor cx,cx    ;load zero
  188.         mov b display_type,cl    ;indicate fit to whatever display
  189.         mov b chart_active,0ffh    ;indicate chart is active
  190.         mov si,o 080h    ;load offset to command tail
  191.         mov cl,b[si]    ;load size of command tail
  192.         jcxz >c2    ;set up stack if no arguments
  193.         inc si    ;move to first character in command tail
  194.  
  195.         ;check if arguments are recognised
  196.  
  197. b1:
  198.         lodsb    ;move to next non white-space character
  199.         cmp al,020h    ;is character white-space?
  200. if be        loop b1    ;read next character if not
  201.         cmp al,'/'    ;start of argument?
  202.         loopne b1    ;read next character if not
  203.         jcxz >c2    ;set up stack if no more arguments
  204.  
  205.         ;check if argument is /m for remain displaying on a monochrome display
  206.  
  207. b2:
  208.         lodsb    ;load argument switch
  209.         and al,05fh    ;make it upper case
  210.         mov dl,7    ;assume specifying monochrome display
  211.         mov bx,03b4h    ;load crtc address for MDA
  212.         cmp al,'M'    ;is it m for monochrome?
  213.         je >a1    ;store option if it is
  214.         mov dl,3    ;assume option is colour
  215.         mov bx,03d4h    ;load crtc address for CGA
  216.  
  217.         ;load whatever crtc address if no display type specified
  218.  
  219.         cmp al,'C'    ;is it c for colour?
  220.         jne >a2    ;check for H for help if not
  221. a1:
  222.         mov w crtc_address,bx    ;save crtc port address
  223.         mov b display_type,dl    ;store display type
  224.         jmp >c2    ;setup stack
  225.  
  226.         ;mark end of filename and check next argument
  227.  
  228. a5:
  229.         mov b[si-1],0    ;mark end of filename
  230.         jmp b2    ;check next argument
  231. c2:
  232.         jmp c1    ;setup stack
  233.  
  234.         ;move to start of filename
  235.  
  236. a3:
  237.         inc si    ;move to next character
  238. a4:
  239.         cmp b[si],020h    ;is next character white space?
  240.         loope a3    ;move to next character if it is
  241.         je c2    ;setup stack if end of command line
  242.  
  243.         ;store zero byte at end of filename
  244.  
  245.         mov w filename,si    ;mark start of filename
  246. a1:
  247.         lodsb    ;move to next character
  248.         cmp al,'/'    ;is character switch?
  249.         je a5    ;mark end of filename if it is
  250.         cmp al,020h    ;is character white space?
  251.         jbe >a5    ;mark end of filename if yes
  252.         loop a1    ;move to next character if not
  253.  
  254.         ;mark end of filename
  255.  
  256.         mov b[si],0    ;mark end of filename
  257.         jmp c2    ;initialise environment
  258. a5:
  259.         mov b[si-1],0    ;mark end of filename
  260.         jmp b1    ;check next item on command line
  261.  
  262.         ;check for command line help
  263.  
  264. a2:
  265.         cmp al,'F'    ;is argument a filename?
  266.         je a4    ;check for help if not
  267. a2:
  268.         cmp al,'H'    ;display banner?
  269.         je >b1    ;display and exit if yes
  270.         cmp al,'?'    ;display banner?
  271.         jne c2    ;setup stack
  272.  
  273.         ;get display page
  274.  
  275. b1:
  276.         xor ax,ax    ;load zero
  277.         mov es,ax
  278.     es    mov al,b[0462h]    ;copy current active video page
  279.         mov b active_page,al
  280.         call get_screen    ;initialise pointers to current mode
  281.  
  282.         ;get cursor position
  283.  
  284.         mov ah,3    ;load function parameter
  285.         mov bh,b active_page    ;load current page
  286.         call int10    ;read cursor position
  287.         xor dl,dl    ;load column 1
  288.         call copyright_message    ;display copyright banner
  289.  
  290.         ;display invocation syntax
  291.  
  292.         call write    ;write title
  293.         db 13,13,'USAGE: CHART /M /H or /?',13
  294.         db '/M stick with monochrome display',13
  295.         db '/C stick with colour display',13
  296.         db '/H or /? this banner',13,0
  297.         mov ax,04c00h    ;exit back to calling process
  298.         int 021h    ;transfer to DOS
  299.  
  300.         ;main loop
  301.  
  302. body:
  303.         mov ds,ax,cs    ;copy segment to workspace
  304.         call clear_cursor    ;clear cursor
  305.         call cls    ;clear the screen
  306.         mov dx,0509h    ;load cursor coords
  307.         call copyright_message    ;display copyright banner
  308.  
  309.         ;write save flowchart option
  310.  
  311.         mov dx,0917h    ;position cursor for first option
  312.         call cursor
  313.         mov al,' '    ;clear option character
  314.         cmp b new_chart,0ffh    ;is there a chart in memory?
  315.         je >a1    ;write option character if not
  316.         cmp b chart_active,080h    ;is chart in interrupt?
  317. if ne        mov al,'1'    ;load option character
  318. a1:
  319.         mov b menu,al    ;indicate option available
  320.         call write_chr    ;write option character to screen
  321.  
  322.         ;write save options
  323.  
  324.         call write    ;write save option
  325.         db ': Save flowchart',0
  326.         mov bx,'3 '    ;load option characters
  327.         cmp b chart_active,080h    ;is chart in interrupt?
  328. if ne        mov bl,'2'    ;load option character
  329.         mov w menu+1,bx    ;indicate options available
  330.         mov al,bl    ;load load file option char
  331.         mov dx,0b17h    ;load cursor coords
  332.         call cursor    ;position cursor
  333.         call write_chr    ;write it to screen
  334.         call write    ;write next option character
  335.         db ': Load flowchart',0
  336.  
  337.         ;write edit options
  338.  
  339.         call writexy    ;write edit option
  340.         db 23,13
  341.         db '3: Edit flowchart',0
  342.         mov bl,' '    ;clear new chart and print chart options
  343.         cmp b new_chart,0ffh    ;is there a flowchart in memory?
  344. if ne        mov bl,'4'
  345.         mov w menu+3,bl    ;indicate options available
  346.  
  347.         ;write clear flowchart option
  348.  
  349.         mov dx,0f17h    ;load cursor coordinates
  350.         call cursor    ;position cursor
  351.         mov al,bl    ;load option
  352.         call write_chr    ;write it to screen
  353.         call write    ;write clear flowchart option
  354.         db ': Clear flowchart',0
  355.  
  356.         ;write print flowchart option
  357.  
  358. ;        mov dx,0f17h    ;load cursor coordinates
  359. ;        call cursor    ;position cursor
  360. ;        mov al,b menu+4    ;load option
  361. ;        call write_chr    ;write it to screen
  362. ;        call write    ;write clear flowchart option
  363. ;        db ': Print flowchart',0
  364.  
  365.         ;write dos shell option to screen
  366.  
  367.         mov al,' '
  368.         cmp b chart_active,080h    ;is chart in interrupt?
  369. if ne        mov al,'5'    ;load option character
  370.         mov b menu+4,al    ;store it
  371.         mov dx,01117h    ;load cursor coords
  372.         call cursor    ;position cursor
  373.         call write_chr    ;write option character
  374.         call write    ;write dos shell option
  375.         db ': Dos shell',0
  376.  
  377.         ;write exit option
  378.  
  379.         call writexy    ;write exit option
  380.         db 23,19
  381.         db '6: Exit',0
  382.         mov b menu+5,'6'    ;indicate option available
  383.         call writexy
  384.         db 20,23
  385.         db 'ESC will bring you back here',0
  386.  
  387.         ;fetch keypress
  388.  
  389. b1:
  390.         call key    ;get keypress
  391.         jnc >a1    ;check if keypress is control code
  392.     cs    mov b middle_5,0    ;cancel quick exit flag
  393.         jmp b1    ;get another key if middle 5 down
  394.  
  395.         ;check keypress
  396.  
  397. a1:
  398.         cmp al,020h    ;is char control code?
  399.         jbe b1    ;get another keypress if it is
  400.         mov cx,menu_options    ;load total menu options
  401.         mov di,o menu    ;load pointer to option string
  402.         mov es,bx,cs
  403.         repne
  404.         scasb
  405.         jne b1    ;get another keypress if not a option
  406.  
  407.         ;check if keypress is for save chart option
  408.  
  409.         cmp al,'1'    ;is it?
  410.         jne >a2    ;check for load chart option if not
  411.         call save_chart    ;save flow chart to disk
  412.         jmp body    ;goto start of main loop
  413.  
  414.         ;check if keypress is for load chart option
  415.  
  416. a2:
  417.         cmp al,'2'    ;is it?
  418.         jne >a2    ;check for edit chart option if not
  419.         call load_chart    ;load flow chart from disk
  420.         mov ds,ax,cs    ;restore data segment register
  421.         jnc >c1    ;rejoin main loop if ok
  422.         cmp w current_box,0    ;is there a chart resident
  423.         je >e2    ;reset variables if not
  424. c1:
  425.         jmp body    ;rejoin main loop if there is
  426.  
  427.         ;check if keypress is for edit chart option
  428.  
  429. a2:
  430.         cmp al,'3'    ;is it?
  431.         jne >a2    ;check for clear chart option if not
  432.         mov bp,w current_box    ;load current box
  433.         call check_memory    ;check if enough memory
  434.         jc >a1    ;return to main loop if not enough space
  435.  
  436.         ;call main editing loop
  437.  
  438.         call flowchart    ;save flow chart to disk
  439.         jc >a3    ;exit if middle 5 down
  440.         or bp,bp    ;normal exit?
  441.         je >e2    ;reset flowchart if error
  442. a1:
  443.         jmp body    ;goto start of main loop if yes
  444.  
  445.         ;exit
  446.  
  447. a3:
  448.         clc    ;indicate ok
  449.         ret    ;exit
  450.  
  451.         ;reset flowchart
  452.  
  453. e2:
  454.         mov ds,ax,cs    ;load segment to workspace
  455.         mov es,ax
  456.         xor ax,ax    ;load zero
  457.         mov b chart_flag,al
  458.         mov w next_box,ax    ;set next vacant box
  459.         mov w current_box,ax
  460.  
  461.         ;clear bookmarks
  462.  
  463.         mov cx,10    ;load bookmark count
  464.         mov di,o bookmarks
  465.         rep
  466.         stosw    ;clear them
  467.         dec al
  468.         mov b new_chart,al    ;clear chart
  469.  
  470.         ;reset address to free memory
  471.  
  472.         mov ax,w chart    ;load base address
  473.         mov dx,w chart+2
  474.         mov w start_free_memory,ax    ;store it as start of free memory
  475.         mov w start_free_memory+2,dx
  476. a1:
  477.         jmp body    ;goto menu
  478.  
  479.         ;check if keypress is for clear chart option
  480.  
  481. a2:
  482.         cmp al,'4'    ;is it?
  483.         jne >a2    ;check for shell option if not
  484.         call tail    ;check if chart has been saved
  485.         jc a1    ;redo menu if escape pressed
  486.         jmp e2    ;clear chart
  487.  
  488.         ;check if keypress is for print chart option
  489.  
  490. ;a2:
  491. ;        cmp al,'5'    ;is it?
  492. ;        jne >a2    ;check for dos shell option if not
  493. ;        call print_chart    ;print chart;
  494. ;        jmp body    ;goto start of main loop
  495.  
  496.         ;check if keypress is for dos shell option
  497.  
  498. a2:
  499.         cmp al,'5'    ;is it?
  500.         jne >a2    ;exit if not
  501.         jmp dos_shell    ;exit to dos shell
  502.  
  503.         ;check for exit option
  504.  
  505. a2:
  506.         cmp al,'6'    ;is keypress for exit?
  507.         je ret    ;exit if it is
  508.         jmp b1    ;get another keypress
  509.  
  510.         ;check if flowchart has changed since last save
  511.  
  512. tail:
  513.         cmp b chart_active,080h    ;is chart in interrupt?
  514.         je ret    ;exit if it is
  515.         cmp b new_chart,080h    ;is there a chart in memory?
  516.         jae ret    ;dont prompt to save it if not
  517.         call clear_line    ;clear bottom lines
  518.         call writexy    ;write save message to screen
  519.         db 24,24
  520.         db 'Flowchart not saved, save (y/n)',0
  521.  
  522.         ;wait for keypress
  523.  
  524. a2:
  525.         call key    ;get keypress
  526.         jnc >a1    ;check if keypress is control code
  527.     cs    mov b middle_5,0    ;cancel quick exit flag
  528.         jmp a2    ;wait for next keypress
  529. a1:
  530.         stc    ;indicate escape pressed
  531.         je ret    ;exit if escape pressed
  532.  
  533.         ;check if user wants to save
  534.  
  535.         and al,05fh    ;make keypress upper case
  536.         cmp al,'N'    ;does user want to save
  537.         je ret    ;exit if not
  538.         cmp al,'Y'    ;save?
  539.         jne a2    ;get another keypress if not
  540.         call save_chart    ;save flowchart
  541.         ret    ;exit
  542.  
  543.         ;save flowchart to disk
  544.  
  545. save_chart:
  546.         call filename_prompt    ;write prompt to bottom line
  547.         call get_string    ;get filename
  548.         dw filename    ;offset to string buffer
  549.         db 64,1    ;maximum string size
  550.         jc ret    ;exit if escape pressed
  551.  
  552.         ;open file for writing
  553.  
  554.         mov dx,si    ;load offset to filename
  555.         mov ah,03ch    ;load function parameter
  556.         xor cx,cx    ;load file attribute
  557.         int 021h    ;create file
  558.         jnc >a1    ;subtract base from descripter
  559.             ;addresses if file created
  560.         call error_exit    ;exit with error
  561.         db 30,'File creation error',0
  562.  
  563.         ;save current box and next new box markers
  564.  
  565. a1:
  566.         mov w handle,ax    ;save handle
  567.         mov bx,ax
  568.         mov ah,040h    ;load function parameter
  569.         mov cx,4    ;load count
  570.         mov dx,o current_box
  571.         int 021h    ;write current box and new box to disk
  572.         jc >b2    ;exit if error
  573.  
  574.         ;subtract base of chart data area from descripter addresses
  575.  
  576. a1:
  577.         mov bx,w chart    ;load base address
  578.         mov dx,w chart+2    ;load high word of base address
  579.         not bx    ;convert to 2s complement
  580.         not dx
  581.         inc bx
  582. if e        inc dx    ;increment if carry
  583.         call chart_addresses    ;subtract base from chart addresses
  584.  
  585.         ;calculate size of data area
  586.  
  587.         mov ax,w start_free_memory    ;load ram top address
  588.         mov dx,w start_free_memory+2
  589.         mov bx,w chart    ;load base address
  590.         mov cx,w chart+2
  591.         sub ax,bx    ;calculate size of data area
  592.         sbb dx,cx
  593.         mov w shift_count,ax    ;save it
  594.         mov w shift_count+2,dx
  595.         mov w temp2,bx    ;save address of data
  596.         mov w temp2+2,cx
  597.  
  598.         ;write box data and descripters store to disk
  599.  
  600. b1:
  601.         call load_count    ;get size of block
  602.         mov si,cx    ;save it
  603.         mov ax,w temp2    ;load start address of block
  604.         mov dx,w temp2+2
  605.         call get_pointer    ;convert it to pointer format
  606.         mov dx,di    ;load offset
  607.         mov bx,w handle    ;load handle to output file
  608.         mov ds,ax,es    ;copy segment
  609.         mov ah,040h    ;load function parameter
  610.         int 021h    ;write block to disk
  611.  
  612.         ;check for error
  613.  
  614.         mov di,cs    ;restore data segment register
  615.         mov ds,di
  616.         mov bx,w handle    ;load handle to output file
  617.         jnc >a1    ;check if all bytes were written if ok
  618.  
  619.         ;close file and exit with error message
  620.  
  621. b2:
  622.         mov ah,03eh    ;load function paramter
  623.         int 021h    ;close file
  624.         call error_exit    ;exit with error
  625.         db 31,'Cant write to disk',0
  626.  
  627.         ;check if all bytes were written to file
  628.  
  629. a1:
  630.         cmp ax,si    ;were they?
  631.         je >a1    ;check if any more bytes to write if yes
  632.         mov ah,03eh    ;load function parameter
  633.         int 021h    ;close file
  634.         call error_exit    ;exit with error message
  635.         db 35,'Disk full',0
  636.  
  637.         ;check if any more bytes to write
  638.  
  639. a1:
  640.         add w temp2,si    ;add bytes written to address
  641.         adc w temp2+2,0
  642.         mov ax,w shift_count    ;is there any more bytes to write
  643.         or ax,w shift_count+2
  644.         jne b1    ;write next block if there is
  645.  
  646.         ;restore box addresses to descripters
  647.  
  648.         mov ah,03eh    ;load function parameter
  649.         int 021h    ;close file
  650.         mov bx,w chart    ;load base address
  651.         mov dx,w chart+2    ;load high word of base address
  652.         or b new_chart,080h    ;indicate chart saved
  653.  
  654.         ;subtract/add chart base address to box descripter addresses
  655.  
  656. chart_addresses:
  657.         mov cx,w next_box    ;load top box
  658.         mov ax,first_box    ;load first box
  659.         sub cx,ax    ;calculate number of boxes in chart
  660.         jcxz ret    ;exit if chart empty
  661.         call get_box    ;get its pointer
  662.  
  663.         ;check if box is deleted
  664.  
  665. a1:
  666.     es    cmp w[di],-1    ;is this box deleted?
  667.         je >a3    ;move to next box if it is
  668.         mov si,20    ;load offset to bookmarks
  669.     es    mov w[di+box_temp],0    ;clear bookmark marker
  670.  
  671.         ;check if current box is boxmarked
  672.  
  673. a2:
  674.         sub si,2    ;move back a bookmark
  675.         jc >a4    ;update descripter address if not marked
  676.         cmp ax,w[si+bookmarks]    ;is current box marked?
  677.         jne a2    ;check next bookmark if not
  678.         shr si,1    ;calculate bookmark id
  679.         inc si
  680.     es    mov w[di+box_temp],si    ;indicate this box is marked
  681.  
  682.         ;update pointers
  683.  
  684. a4:
  685.     es    add w[di+descripter],bx    ;add/subtract base address
  686.     es    adc w[di+descripter+2],dx
  687. a3:
  688.         inc ax    ;increment box marker
  689.         call add_record    ;move to next box
  690.         loop a1    ;decrement loop count
  691.         clc    ;indicate chart loaded/saved
  692.         ret    ;exit
  693.  
  694.         ;subtract/add chart base address to box descripter addresses
  695.  
  696. chart_addresses2:
  697.         mov ax,first_box    ;load first box
  698.         sub cx,ax    ;calculate number of boxes in chart
  699.         jcxz ret    ;exit if chart empty
  700.         call get_box    ;get its pointer
  701.  
  702.         ;update pointers
  703.  
  704. a1:
  705.     es    add w[di+descripter],bx    ;add/subtract base address
  706.     es    adc w[di+descripter+2],dx
  707.         call add_record    ;move to next box
  708.         loop a1    ;decrement loop count
  709.         clc    ;indicate chart loaded/saved
  710.         ret    ;exit
  711.  
  712.         ;subtract/add chart base address to box descripter addresses
  713.  
  714. chart_bookmarks:
  715.         mov ax,first_box    ;load first box
  716.         mov cx,w next_box    ;calculate number of boxes in chart
  717.         sub cx,ax
  718.         jcxz ret    ;exit if chart empty
  719.         call get_box    ;get its pointer
  720.  
  721.         ;update pointers
  722.  
  723. a1:
  724.     es    cmp w[di],-1    ;is this box deleted?
  725.         je >a3    ;move to next box if it is
  726.     es    mov si,w[di+box_temp]    ;load box marker flag
  727.         dec si    ;correct it
  728.         cmp si,9    ;is this box marked?
  729.         ja >a3    ;update descripter if not
  730.         shl si,1    ;calculate offset to bookmark
  731.         mov w[si+bookmarks],ax    ;store bookmark
  732.  
  733.         ;update descripter pointer
  734.  
  735. a3:
  736.         inc ax    ;increment box marker
  737.         call add_record    ;move to next box
  738.         loop a1    ;decrement loop count
  739.         clc    ;indicate chart loaded/saved
  740.         ret    ;exit
  741.  
  742.         ;write error message and exit
  743.  
  744. error_exit:
  745.         call clear_line    ;clear bottom lines
  746.         pull si    ;load address of message
  747.         lodsb    ;load cursor coords
  748.         mov dl,al
  749.         mov dh,24
  750.         call cursor    ;position cursor
  751. a1:
  752.         lodsb    ;load character from message
  753.         or al,al    ;end of string?
  754.         je >a2    ;wait for keypress if it is
  755.         call write_chr    ;write it to bottom line
  756.         jmp a1    ;get next character
  757.  
  758.         ;wait for keypress
  759.  
  760. a2:
  761.         call key    ;wait for keypress
  762.     cs    mov b middle_5,0    ;cancel quick exit flag
  763.         stc    ;indicate error
  764.         ret    ;exit
  765.  
  766.         ;write prompt to bottom line
  767.  
  768. filename_prompt:
  769.         call clear_line    ;clear bottom lines
  770.         call writexy    ;write prompt
  771.         db 27,24
  772.         db 'Please enter path/filename',0
  773.         ret    ;exit
  774.  
  775.         ;exit from here if middle 5 on numeric keypad is down
  776.  
  777. b1:
  778.         cmp b middle_5,0    ;has it been pressed?
  779.         je flowchart    ;don't exit from here if not
  780.         stc    ;indicate middle 5 on keypad pressed
  781.         ret    ;exit if it has
  782.  
  783.         ;main editing loop
  784.  
  785. flowchart:
  786.         call get_options    ;get options available
  787. a1:
  788.         call write_chart    ;write options and chart to screen
  789.         call do_option    ;process option select
  790.         jc b1    ;get options if escape not pressed
  791.         jne a1    ;write chart again if escape not pressed
  792.         ret    ;exit
  793.  
  794.         ;get string from keyboard input
  795.  
  796. get_string:
  797.         pull si    ;get offset to string
  798.         lodsw
  799.         mov w start_string,ax    ;save it
  800.         lodsw    ;read maximum string length
  801.         push si    ;save return address
  802.         mov b escape_flag,ah    ;store flag
  803.         xor ah,ah    ;clear high order register
  804.         dec ax    ;adjust it
  805.         add ax,w start_string    ;calculate offset to end of string
  806.         mov w end_string,ax    ;save it
  807.  
  808.         ;save cursor position
  809.  
  810.         push bx,di,es    ;save pointer
  811.         mov dx,01700h    ;load cursor coordinates
  812.         mov w edit_cursor,dx
  813.         mov di,w start_string    ;load offset to start of string
  814.         mov es,ax,cs    ;copy code segment
  815.         mov w start_string_screen,di    ;store it as start of string on screen
  816.  
  817.         ;position cursor
  818.  
  819. c1:
  820.         mov si,w start_string_screen    ;load offset to start of string
  821.         mov dx,01700h    ;load position for start of string
  822.         call cursor    ;position cursor
  823.         call clear_cursor    ;clear cursor
  824.         mov cx,79    ;load count
  825.  
  826.         ;write string to screen
  827.  
  828. a1:
  829.         lodsb    ;load character from string
  830.         or al,al    ;end of string?
  831.         je >a2    ;get keypress if it is
  832.         call write_chr    ;write character to screen
  833.         loop a1    ;decrement loop count
  834.  
  835.         ;write spaces at end of string
  836.  
  837. a2:
  838.         jcxz >a1    ;position cursor in string if line full
  839.         mov al,' '    ;finish off string with space
  840. a2:
  841.         call write_chr
  842.         loop a2    ;decrement loop count
  843.  
  844.         ;position cursor
  845.  
  846. a1:
  847.         mov cx,0ch    ;load cursor rows
  848.         call set_cursor    ;set cursor type
  849.         mov dx,w edit_cursor    ;load cursor position
  850.         call cursor    ;position cursor
  851.  
  852.         ;get keypress
  853.  
  854. c2:
  855.         call key    ;get keypress
  856.     cs    mov b middle_5,0    ;cancel quick exit flag
  857.         jc c2    ;get another keypress
  858.         jne >b1    ;check for right key if escape not down
  859.         cmp b escape_flag,0    ;is escape enabled?
  860.         je c2    ;get another key if not
  861.         call clear_cursor    ;clear the cursor
  862.         pull es,di,bx    ;restore pointer
  863.         stc
  864.         ret    ;exit
  865.  
  866.         ;check for right arrow key
  867.  
  868. b1:
  869.         cmp ax,04d00h    ;is keypress right key?
  870.         jne >b1    ;check for left key if not
  871.         call move_right    ;move cursor right one space
  872.         je c2    ;get keypress if at end of string
  873.         jmp c1    ;display string
  874.  
  875.         ;check for left arrow key
  876.  
  877. b1:
  878.         cmp ax,04b00h    ;is keypress left key?
  879.         jne >b1    ;check for home if not
  880.         call move_left    ;move cursor left
  881.         je c2    ;get keypress if at start of string
  882.         jmp c1    ;display string
  883.  
  884.         ;check for home key
  885.  
  886. b1:
  887.         cmp ax,04700h    ;is keypress home key?
  888.         jne >b1    ;check for end if not
  889. a1:
  890.         call move_left    ;move cursor left
  891.         jne a1    ;keep on moving until at start of string
  892.         jmp c1    ;display string
  893.  
  894.         ;check for end key
  895.  
  896. b1:
  897.         cmp ax,04f00h    ;is keypress left key?
  898.         jne >b1    ;check for ctrl left if not
  899. a1:
  900.         call move_right    ;move cursor left
  901.         jne a1    ;keep on moving until at start of string
  902.         jmp c1    ;display string
  903.  
  904.         ;check for ctrl left arrow key (move cursor left a word)
  905.  
  906. b1:
  907.         cmp ax,07300h    ;is keypress ctrl left key?
  908.         jne >b1    ;check for ctrl right if not
  909.         call move_left    ;move left a character
  910.         je c2    ;get keypress if at start of string
  911.         mov w temp2,o move_left    ;store calling address
  912.         call ctrl_lr    ;move to next word
  913. if ne        call move_right    ;move cursor over first chr in word
  914.         jmp c1    ;display string
  915.  
  916.         ;check for ctrl right arrow key (move cursor right a word)
  917.  
  918. b1:
  919.         cmp ax,07400h    ;is keypress ctrl right key?
  920.         jne >b1    ;check for ctrl end if not
  921.         mov w temp2,o move_right    ;store calling address
  922.         call ctrl_lr    ;move to next word
  923.         jmp c1    ;display string
  924.  
  925.         ;check for ctrl end key (delete to end of line)
  926.  
  927. b1:
  928.         cmp ax,07500h    ;is keypress ctrl end key?
  929.         jne >b1    ;check for return if not
  930.         mov b[di],0    ;delete to end of string
  931.         jmp c1    ;display string
  932.  
  933.         ;check for carriage return
  934.  
  935. b1:
  936.         cmp al,0dh    ;is keypress carriage return?
  937.         jne >b1    ;check for backspace if not
  938.         mov si,w start_string    ;load offset to start of string
  939.         cmp b[si],0    ;is it empty?
  940. c3:
  941. if e        jmp c2    ;get another keypress if it is
  942.  
  943.         ;calculate length of string
  944.  
  945.         push si    ;save offset
  946.         mov cx,-1    ;clear count
  947. a1:
  948.         lodsb    ;load character from string
  949.         inc cx    ;increment count
  950.         or al,al    ;end of string?
  951.         jne a1    ;read next character
  952.         call clear_cursor    ;clear the cursor
  953.         pull si,es,di,bx    ;restore pointer
  954.         ret    ;exit
  955.  
  956.         ;check for backspace key
  957.  
  958. b1:
  959.         cmp ax,0e08h    ;is keypress backspace key?
  960.         jne >b1    ;check if it is delete key if not
  961.         cmp di,w start_string    ;is offset at start of string?
  962.         je c3    ;get another keypress if it is
  963.         dec di    ;decrement offset
  964.  
  965.         ;decrement cursor column
  966.  
  967.         cmp b edit_cursor,0    ;is cursor at end of line?
  968.         ja >a1    ;increment column coordinate if not
  969.         dec w start_string_screen    ;increment offset to start of string
  970.         jmp >b2    ;write string to screen
  971. a1:
  972.         dec b edit_cursor    ;decrement cursor column
  973.         jmp >b2    ;delete character at cursor
  974.  
  975.         ;check for delete key
  976.  
  977. b1:
  978.         cmp ax,05300h    ;is keypress delete key?
  979.         jne >b1    ;check if it is alphanumeric if not
  980.         cmp b[di],0    ;is offset at end of string?
  981.         je >c3    ;get another keypress if it is
  982. b2:
  983.         mov bx,di    ;load string offset
  984.         dec bx    ;adjust offset
  985. a1:
  986.         inc bx    ;increment offset
  987.         mov al,b[bx+1]    ;move next character down
  988.         mov b[bx],al
  989.         or al,al    ;end of string?
  990.         jne a1    ;move next character if not
  991.         jmp c1    ;write string to screen
  992. c3:
  993.         jmp c2    ;fetch another keypress
  994.  
  995.         ;check if keypress is alphanumeric
  996.  
  997. b1:
  998.         cmp al,020h    ;is keypress with ctrl or alt key?
  999.         jb c3    ;fetch another keypress if it is
  1000.         cmp di,w end_string    ;is string full?
  1001.         je c3    ;fetch another keypress if it is
  1002.  
  1003.         ;insert character into string
  1004.  
  1005.         mov bx,w end_string    ;load offset to end of string
  1006.         inc bx
  1007.         mov b[bx+1],0    ;mark end of string
  1008. a1:
  1009.         dec bx    ;decrement offset
  1010.         mov ah,b[bx]    ;load character at end of string
  1011.         mov b[bx+1],ah    ;move it up one
  1012.         cmp bx,di    ;is offset at cursor position?
  1013.         ja a1    ;move next character if not
  1014.         stosb    ;store character in string
  1015.  
  1016.         ;increment cursor column
  1017.  
  1018.         cmp b edit_cursor,79    ;is cursor at end of line?
  1019.         jb >a1    ;increment column coordinate if not
  1020.         inc w start_string_screen    ;increment offset to start of string
  1021.         jmp c1    ;write string to screen
  1022. a1:
  1023.         inc b edit_cursor    ;increment cursor column
  1024.         jmp c1    ;write string to screen
  1025.  
  1026.         ;move cursor word left/right
  1027.  
  1028. ctrl_lr:
  1029.         mov al,b[di]    ;load character at cursor
  1030.         cmp al,' '    ;is it a space?
  1031. if ne        xor al,al    ;search for next space if not
  1032.         mov dl,al    ;load search character
  1033.         mov b temp3,0    ;store loop count
  1034.         xor dl,' '    ;flip flag
  1035. if e        inc b temp3    ;search for non space then space
  1036.  
  1037.         ;search for space/non space character
  1038.  
  1039. a1:
  1040.         call w temp2    ;move cursor left/right
  1041.         je ret    ;exit if at start/end of line
  1042.         mov al,b[di]    ;load character at cursor
  1043.         cmp al,dl    ;is it Space character?
  1044.         je >a3    ;check if at end of next word if it is
  1045.         cmp al,' '    ;is scan character non space?
  1046.         Je a1    ;decrement loop count if it is
  1047.         Cmp dl,' '    ;is scan character space?
  1048.         Je a1    ;decrement loop count if it is
  1049.  
  1050.         ;switch scan character
  1051.  
  1052. a3:
  1053.         xor dl,' '    ;switch    scan character
  1054.         dec B temp3    ;decrement loop    count
  1055.         je a1    ;search for next space character if
  1056.             ;character was non space
  1057.         ret    ;exit
  1058.  
  1059.         ;move cursor right one space
  1060.  
  1061. move_left:
  1062.         cmp di,w start_string    ;is string maximum size?
  1063.         je ret    ;get another keypress if it is
  1064.         dec di    ;decrement offset
  1065.         cmp b edit_cursor,0    ;is cursor at start of line?
  1066.         ja >a1    ;decrement column coordinate if not
  1067.         dec w start_string_screen    ;decrement offset to start of string
  1068.         ret    ;exit
  1069. a1:
  1070.         dec b edit_cursor    ;decrement cursor position
  1071.         or ax,di    ;indicate cursor moved
  1072.         ret    ;exit
  1073.  
  1074.         ;move cursor right one space
  1075.  
  1076. move_right:
  1077.         cmp b[di],0    ;is cursor at end of string?
  1078.         je ret    ;exit if it is
  1079.         cmp di,w end_string    ;is string maximum size?
  1080.         je ret    ;exit if it is
  1081.         inc di    ;increment offset
  1082.         cmp b edit_cursor,79    ;is cursor at end of line?
  1083.         jb >a1    ;increment column coordinate if not
  1084.         inc w start_string_screen    ;increment offset to start of string
  1085.         ret    ;exit
  1086. a1:
  1087.         inc b edit_cursor    ;increment cursor position
  1088.         ret    ;position cursor
  1089.  
  1090.         ;read cursor position coordinates and position cursor
  1091.  
  1092. writexy:
  1093.         pull si    ;load offset to cursor coords
  1094.         lodsw    ;read cursor coords
  1095.         mov dx,ax
  1096. c1:
  1097.         call cursor    ;position cursor
  1098.         push si    ;save offset to string
  1099.  
  1100.         ;write string following calling address
  1101.  
  1102. write:
  1103.         pull si    ;load offset to string
  1104.         mov bl,novid    ;load attribute
  1105.         mov ah,bl
  1106.         mov b attribute,bl    ;store darker colour
  1107.         push di,es    ;save pointer
  1108.         les di,w video_pointer    ;load pointer to video map
  1109.  
  1110.         ;read character from calling procedure
  1111.  
  1112. b1:
  1113.         lodsb    ;read character from string
  1114.         or al,al    ;last character?
  1115.         jne >a1    ;check video flag if not
  1116.         mov w video_pointer,di    ;save pointer to video map
  1117.         pull es,di    ;restore pointer
  1118.         jmp si    ;exit if it is
  1119.  
  1120.         ;check for carriage return
  1121.  
  1122. a1:
  1123.         cmp al,13    ;carriage return?
  1124.         jne >a1    ;output character if not
  1125.         push ax,bx,cx,dx,si,di,bp    ;save registers
  1126.         mov bx,w attribute    ;load attribute and active page
  1127.         mov ah,0eh    ;output carraige to bios teletype fn
  1128.         call int10    ;call bios
  1129.         mov ax,0e0ah    ;output line feed
  1130.         call int10    ;call bios
  1131.         pull bp,di,si,dx,cx,bx,ax    ;restore registers
  1132.  
  1133.         ;reposition video pointer
  1134.  
  1135.         mov dx,w cursorxy    ;load cursor row position
  1136.         xor dl,dl    ;set start of row
  1137.         cmp dh,24    ;is cursor on bottom row?
  1138. if b        inc dh    ;move to next row if not
  1139.         jmp c1    ;read next character
  1140.  
  1141.         ;write character to screen
  1142.  
  1143. a1:
  1144.         cmp b direct_video,0    ;write direct to video map?
  1145.         jne >a1    ;write char and attribute to map if yes
  1146.         call write_chr    ;write character to screen
  1147.         jmp b1    ;read next character
  1148. a1:
  1149.         stosw    ;write chara and attribute to video map
  1150.         jmp b1    ;read next char
  1151.  
  1152.         ;write character to screen
  1153.  
  1154. write_chr:
  1155.         push ax,bx,cx,dx,si,di,bp    ;save registers
  1156.     cs    mov bx,w attribute    ;load active page
  1157.     cs    cmp b direct_video,0    ;is screen output direct?
  1158.         je >a1    ;write char through bios if not
  1159.  
  1160.         ;write char direct to video memory
  1161.  
  1162.         push es    ;save pointer
  1163.     cs    les di,w video_pointer    ;load pointer to video map
  1164.         mov ah,bl    ;load attribute]
  1165.         stosw    ;write it and char to video memory
  1166.     cs    mov w video_pointer,di    ;save pointer to video map
  1167.         pull es    ;restore pointer
  1168.         jmp >a2
  1169.  
  1170.         ;write character via bios
  1171.  
  1172. a1:
  1173.         mov ah,3    ;load function parameter
  1174.         push bx    ;save register
  1175.         call int10    ;read cursor position
  1176.         mov ah,9    ;load funtion parameter
  1177.         pull bx    ;load active page
  1178.         push dx,bx    ;save registers
  1179.         mov cx,1    ;load character    count
  1180.         call int10    ;print the character
  1181.         pull bx,dx    ;restore page and cursor coords
  1182.         cmp dl,80    ;is it beyond right of screen
  1183. if b        inc dl    ;increment x coordinate
  1184.         mov ah,2    ;load set cursor function parameter
  1185.         call int10    ;advance cursor
  1186. a2:
  1187.         pull bp,di,si,dx,cx,bx,ax    ;restore registers
  1188.         ret
  1189.  
  1190.         ;set 80x25 text display mode
  1191.  
  1192. init_screen:
  1193.         push ds    ;save register
  1194.         mov al,b display_type    ;set 80x25 text    display
  1195.         xor dx,dx    ;load segment to bios workspace
  1196.         mov ds,dx
  1197.         or al,al    ;fit with whatever display is in use?
  1198.         jne >a1    ;set display mode if not
  1199.         mov al,b[0449h]    ;load video mode
  1200.         mov ah,al
  1201.         mov bh,b[0462h]
  1202.  
  1203.         ;set display mode
  1204.  
  1205.         cmp al,2    ;is display text (80x25)
  1206.         je >a2    ;set video map pointeers if it is
  1207.         cmp al,3    ;is current display mode text?
  1208.         je >a2    ;set video map pointeers if it is
  1209.         cmp al,7    ;is display monochrome?
  1210.         je >a2    ;set video map pointeers if it is
  1211.         mov al,3    ;set 80x25 text if not text mode
  1212.  
  1213.         ;force 80x25 colour text mode
  1214.  
  1215. a1:
  1216.         call int10    ;call bios
  1217.         mov al,b[0449h]    ;load video mode
  1218.         mov ah,al
  1219.         mov bh,b[0462h]
  1220.         jmp >a2    ;calculate pointers to video map
  1221.  
  1222.         ;set pointers to screen
  1223.  
  1224. get_screen:
  1225.         push ds    ;save register
  1226.         mov bh,b active_page    ;load page last active
  1227.         mov al,b display_type    ;load fixed display type
  1228.         xor dx,dx    ;load segment to bios workspace
  1229.         mov ds,dx
  1230.  
  1231.         ;load currently displayed video mode
  1232.  
  1233.         mov ah,b[0449h]    ;load video mode if yes
  1234.         or al,al    ;is display fixed?
  1235.         jne >a2    ;calculate pointers to video map if yes
  1236.         mov al,ah    ;load video mode if yes
  1237.         mov bh,b[0462h]
  1238.  
  1239.         ;store variables
  1240.  
  1241. a2:
  1242.         mov dx,ax    ;copy video modes
  1243.         sub dl,dh    ;if displays are cga then count as same
  1244. if c        neg dl    ;get difference
  1245.         cmp dl,3    ;is video mode cga?
  1246. if be        mov al,ah    ;make both modes same
  1247.  
  1248.         ;store current video page
  1249.  
  1250.     cs    mov b active_page,bh    ;store it
  1251.         mov bl,b[0462h]    ;calculate offset to cursor coordinates
  1252.         xor bh,bh
  1253.         shl bx,1
  1254.         mov dx,w[bx+0450]    ;get cursor coords
  1255.         mov cx,w[0460]    ;get cursor type
  1256.  
  1257.         ;calculate base address to current video mode
  1258.  
  1259.         mov bx,0b800h    ;load video memory base address
  1260.         cmp al,3    ;is video mode for cga?
  1261. if ne        mov bx,0b000h    ;load base video ram address for mda
  1262.         pull ds    ;restore register
  1263.         mov w video_base,bx    ;store video memory base address
  1264.         ret    ;exit
  1265.  
  1266.         ;calculate offset to video memory
  1267.  
  1268. cursor:
  1269.         push ax,bx,cx,dx,si,di,bp    ;save registers
  1270.     cs    mov bh,b active_page    ;load video page
  1271.     cs    mov w cursorxy,dx    ;save cursor postion
  1272.         mov al,bh    ;load video page
  1273.         cbw    ;sign extend
  1274.         mov cl,12    ;multiply page by 4096
  1275.         shl ax,cl
  1276.         mov di,ax    ;store it in offset
  1277.         mov al,dh    ;load cursor row
  1278.         cbw    ;sign extend
  1279.         push dx    ;save cursor coords
  1280.         mov dx,ax    ;save offset to start of page
  1281.         shl ax,1    ;x 2
  1282.         shl ax,1    ;x 4
  1283.         add ax,dx    ;x 5
  1284.         mov cl,5    ;x 160
  1285.         shl ax,cl
  1286.         add di,ax    ;add it    to active page offset
  1287.         pull dx    ;restore cursor coords
  1288.         mov al,dl    ;load cursor coords
  1289.         cbw    ;sign extend
  1290.         shl ax,1    ;multiply column offset    by two
  1291.         add di,ax    ;add it    to active page and row
  1292.     cs    mov w video_pointer,di    ;save offset to video map
  1293.  
  1294.         ;position cursor
  1295.  
  1296.     cs    cmp b chart_active,080h    ;is program in dos shell?
  1297.         je >b1    ;program video hardware directly
  1298.         mov ah,2    ;load function parameter
  1299.         call int10    ;position cursor if not
  1300.         jmp >c1    ;exit
  1301.  
  1302.         ;program video hardware to position cursor
  1303.  
  1304. b1:
  1305.     cs    cmp b cursor_on,0    ;is cursor displayed?
  1306.         je >c1    ;exit if not
  1307. b1:
  1308.     cs    mov dx,w crtc_address    ;load crtc register address port
  1309.         shr di,1    ;convert word address to byte address
  1310.         mov bx,di    ;load cursor offset
  1311.  
  1312.         ;set cursor location address high word
  1313.  
  1314.         mov al,o crtc_clochigh    ;load register address
  1315.         out dx,al
  1316.         mov al,bh    ;copy msb to crtc
  1317.         inc dx
  1318.         out dx,al
  1319.         dec dx
  1320.  
  1321.         ;set cursor location address low word
  1322.  
  1323.         mov al,o crtc_cloclow    ;load register address
  1324.         out dx,al
  1325.         inc dx
  1326.         mov al,bl    ;copy lsb to crtc
  1327.         out dx,al
  1328.  
  1329.         ;exit
  1330.  
  1331. c1:
  1332.         pull bp,di,si,dx,cx,bx,ax    ;restore registers
  1333.         clc    ;indicate no errors
  1334.         ret    ;exit
  1335.  
  1336.         ;clear cursor
  1337.  
  1338. clear_cursor:
  1339.         push ax,bx,cx,dx,si,di,bp    ;save registers
  1340.     cs    mov b cursor_on,0    ;indicate cursor not displayed
  1341.         mov bx,-1    ;throw cursor out of range of screen
  1342.     cs    cmp b chart_active,080h    ;is program in dos shell?
  1343.         je b1    ;program video hardware directly
  1344.         mov ah,1    ;load function parameter
  1345.     cs    mov bh,b active_page    ;load current page
  1346.         mov cx,02000h    ;cursor will dissapear
  1347.         call int10    ;clear cursor
  1348.         jmp c1    ;exit
  1349.  
  1350.         ;Set cursor type
  1351.  
  1352. restore_cursor:
  1353.         mov cx,w exit_cursor_type    ;restore state of cursor
  1354. set_cursor:
  1355.         push ax,bx,cx,dx,si,di,bp    ;save registers
  1356.     cs    mov b cursor_on,0ffh    ;indicate cursor displayed
  1357.     cs    cmp b chart_active,080h    ;is program in dos shell?
  1358.         je >b1    ;program video hardware directly
  1359.         mov ah,1    ;load function parameters
  1360.     cs    mov bh,b active_page    ;load current video map page
  1361.         call int10    ;set cursor type
  1362.         jmp c1    ;exit
  1363.  
  1364.         ;program cursor hardware directly
  1365.  
  1366. b1:
  1367.         mov bx,cx    ;copy scan rows
  1368.         push es    ;save segment register
  1369.         xor ax,ax    ;load zero page
  1370.         mov es,ax
  1371.     cs    mov dx,w crtc_address    ;load crtc address register port
  1372.  
  1373.         ;copy cursor start address
  1374.  
  1375.         mov al,o crtc_cstart    ;load cursor start register address
  1376.         out dx,al    ;select cursor start address
  1377.         mov al,bh    ;load cursor
  1378.         inc dx    ;move to crtc read/write address
  1379.         out dx,al
  1380.         dec dx    ;move to crtc register select address
  1381.  
  1382.         ;copy cursor end address
  1383.  
  1384.         mov al,o crtc_cend    ;load cursor end register address
  1385.         out dx,al    ;select cursor end address
  1386.         mov al,bl    ;load cursor
  1387.         inc dx    ;move to crtc read/write address
  1388.         out dx,al
  1389.     es    mov w[0460h],bx
  1390.         pull es    ;restore register
  1391.         jmp c1    ;exit
  1392.  
  1393.         ;display copyright banner to display
  1394.  
  1395. copyright_message:
  1396.         call cursor    ;position cursor
  1397.         call write    ;write title
  1398.         db 'Chart 1.23 Copyright 1992-1993 Andrew Sprott. All rights reserved.',0
  1399.         ret    ;exit
  1400.  
  1401.         ;end
  1402.